package com.android.lovely.ui.widget

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.text.Layout
import android.text.StaticLayout
import android.util.AttributeSet
import androidx.core.content.ContextCompat
import com.android.lovely.R
import com.kotlin.extensions.dimen.Dimension.dp
import com.kotlin.extensions.view.ViewExt.clickable
import com.liupei.shape.widget.ShapeTextView

class ExpandableTextView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ShapeTextView(context, attrs, defStyleAttr) {

    // 文本视图状态接口
    private interface TextViewState {
        fun getMaxLines(): Int
        fun getIndicator(): Drawable?
        fun toggle(): TextViewState
    }

    // 文本截断策略接口
    private interface TextTruncateStrategy {
        fun truncateText(text: String, width: Float, paint: android.graphics.Paint): String
    }

    // 指示器绘制策略接口
    private interface IndicatorDrawStrategy {
        fun calculateBounds(view: ExpandableTextView, indicator: Drawable, baseline: Int, lineHeight: Float): android.graphics.Rect
        fun drawIndicator(canvas: Canvas, indicator: Drawable)
    }

    // 展开状态实现
    private inner class ExpandedState : TextViewState {
        override fun getMaxLines(): Int = Int.MAX_VALUE
        override fun getIndicator(): Drawable? = collapseIndicator
        override fun toggle(): TextViewState = CollapsedState()
    }

    // 折叠状态实现
    private inner class CollapsedState : TextViewState {
        override fun getMaxLines(): Int = defaultLineLimit
        override fun getIndicator(): Drawable? = expandIndicator
        override fun toggle(): TextViewState = ExpandedState()
    }

    // 省略号文本截断策略实现
    private inner class EllipsisTextTruncateStrategy : TextTruncateStrategy {
        override fun truncateText(text: String, width: Float, paint: android.graphics.Paint): String {
            var truncatedText = text
            while (paint.measureText(truncatedText) > width && truncatedText.isNotEmpty()) {
                truncatedText = truncatedText.dropLast(1)
            }
            return "$truncatedText…" // 添加省略号
        }
    }

    // 默认指示器绘制策略实现
    private inner class DefaultIndicatorDrawStrategy : IndicatorDrawStrategy {
        override fun calculateBounds(
            view: ExpandableTextView,
            indicator: Drawable,
            baseline: Int,
            lineHeight: Float
        ): android.graphics.Rect {
            val indicatorSize = 20.dp
            val indicatorX = (view.width - view.paddingEnd - indicatorSize).toFloat()
            val indicatorY = (baseline - lineHeight / 2 - 2.dp)

            return android.graphics.Rect(
                indicatorX.toInt(),
                indicatorY.toInt(),
                (indicatorX + indicatorSize).toInt(),
                (indicatorY + indicatorSize).toInt()
            )
        }

        override fun drawIndicator(canvas: Canvas, indicator: Drawable) {
            canvas.save()
            indicator.draw(canvas)
            canvas.restore()
        }
    }

    // 属性和状态
    private var currentState: TextViewState = CollapsedState()
    private val expandIndicator: Drawable? by lazy {
        ContextCompat.getDrawable(context, R.drawable.icon_text_bottom)
    }
    private val collapseIndicator: Drawable? by lazy {
        ContextCompat.getDrawable(context, R.drawable.icon_text_up)
    }
    private var indicatorPadding = 5.dp
    private var defaultLineLimit = 2

    // 策略实例
    private val truncateStrategy: TextTruncateStrategy = EllipsisTextTruncateStrategy()
    private val indicatorDrawStrategy: IndicatorDrawStrategy = DefaultIndicatorDrawStrategy()

    init {
        maxLines = currentState.getMaxLines()
        clickable { switchExpandState() }
    }

    /**
     * 设置指示器颜色
     */
    fun setIndicatorTint(color: Int) {
        expandIndicator?.setTint(color)
        collapseIndicator?.setTint(color)
        invalidate()
    }

    /**
     * 设置默认行数限制
     */
    fun setDefaultLineLimit(limit: Int) {
        if (limit > 0) {
            defaultLineLimit = limit
            if (currentState is CollapsedState) {
                maxLines = defaultLineLimit
                requestLayout()
                invalidate()
            }
        }
    }

    override fun onDraw(canvas: Canvas) {
        val currentIndicator = currentState.getIndicator() ?: return
        val layout = layout ?: return
        val totalLineCount = calculateLineCount()

        // 如果文本行数少于最大限制行数，使用系统默认绘制
        if (totalLineCount <= maxLines && totalLineCount <= defaultLineLimit) {
            super.onDraw(canvas)
            return
        }

        drawExtendedText(canvas, layout, currentIndicator)
    }

    /**
     * 绘制扩展的文本视图 - 处理折叠/展开状态下的文本和指示器
     */
    private fun drawExtendedText(canvas: Canvas, layout: Layout, indicator: Drawable) {
        val displayedLineCount = layout.lineCount.coerceAtMost(maxLines)
        val finalLine = displayedLineCount - 1

        val baseline = layout.getLineBaseline(finalLine)
        val lineStartPos = layout.getLineStart(finalLine)
        val lineEndPos = layout.getLineEnd(finalLine)

        val finalLineWidth = paint.measureText(text.substring(lineStartPos, lineEndPos))
        val metrics = paint.fontMetrics
        val lineHeight = metrics.bottom - metrics.top

        // 使用指示器绘制策略计算边界
        val indicatorBounds = indicatorDrawStrategy.calculateBounds(
            this, indicator, baseline, lineHeight
        )
        indicator.bounds = indicatorBounds

        // 计算最大文本宽度并处理截断
        val indicatorSize = 20.dp
        val availableWidth = width - paddingEnd - indicatorSize - indicatorPadding - paddingLeft

        // 处理文本截断
        val finalText: String = if (finalLineWidth > availableWidth) {
            // 使用截断策略
            truncateStrategy.truncateText(text.substring(lineStartPos, lineEndPos),
                availableWidth.toFloat(), paint)
        } else {
            text.substring(lineStartPos, lineEndPos)
        }

        // 绘制文本
        drawTextContent(canvas, layout, displayedLineCount, finalLine, finalText, baseline)

        // 使用指示器绘制策略绘制指示器
        indicatorDrawStrategy.drawIndicator(canvas, indicator)
    }

    /**
     * 绘制文本内容
     */
    private fun drawTextContent(
        canvas: Canvas,
        layout: Layout,
        displayedLineCount: Int,
        finalLine: Int,
        finalText: String,
        baseline: Int
    ) {
        canvas.drawColor(Color.TRANSPARENT)
        paint.color = currentTextColor

        // 绘制除最后一行外的所有行
        for (i in 0 until displayedLineCount - 1) {
            val lineBaseline = layout.getLineBaseline(i)
            val start = layout.getLineStart(i)
            val end = layout.getLineEnd(i)
            canvas.drawText(
                text.substring(start, end),
                paddingLeft.toFloat(),
                lineBaseline.toFloat(),
                paint
            )
        }

        // 绘制最后一行
        canvas.drawText(
            finalText,
            paddingLeft.toFloat(),
            baseline.toFloat(),
            paint
        )
    }

    /**
     * 切换展开/折叠状态
     */
    fun switchExpandState() {
        val totalLineCount = calculateLineCount()
        if (totalLineCount > defaultLineLimit) {
            currentState = currentState.toggle()
            maxLines = currentState.getMaxLines()
            requestLayout()
            invalidate()
        }
    }

    /**
     * 计算文本的总行数
     */
    private fun calculateLineCount(): Int {
        val availableWidth = width - paddingLeft - paddingRight
        val tempLayout = StaticLayout.Builder.obtain(text, 0, text.length, paint, availableWidth)
            .setAlignment(Layout.Alignment.ALIGN_NORMAL)
            .setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
            .build()
        return tempLayout.lineCount
    }

    /**
     * 获取当前展开/折叠状态
     */
    fun isExpanded(): Boolean = currentState is ExpandedState

    override fun performClick(): Boolean {
        super.performClick()
        return true
    }
}